/* 标准库 */
#include "utils/socket.h"
#include <cstdio>
#include <iostream>
#include <vector>
#include <string>
#include <memory>
#ifdef WIN32
#include <ws2tcpip.h>
#include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib")
#define SOCKET_WOULD_BLOCK WSAEWOULDBLOCK
#define SOCKET_IN_PROGRESS WSAEINPROGRESS
#else
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/socket.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#define SOCKET_WOULD_BLOCK EWOULDBLOCK
#define SOCKET_IN_PROGRESS EINPROGRESS
#endif
#include <mutex>


using namespace std;

// --- 平台抽象层 ---
#ifdef WIN32
int  SOCKETERR() { return WSAGetLastError(); }
void SOCKETCLOSE(int fd) { closesocket(fd); }
#else
int  SOCKETERR() { return errno; }
void SOCKETCLOSE(int fd) { close(fd); }
#endif

// --- Windows Sockets 初始化 ---
#ifdef WIN32
namespace {
	struct WinSockInitializer {
		WinSockInitializer() {
			WSADATA wsaData;
			if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
				throw runtime_error("WSAStartup failed");
			}
		}
		~WinSockInitializer() { WSACleanup(); }
	};
	// 全局实例，程序启动时初始化，结束时清理
	static WinSockInitializer g_winSockInit;
} // namespace
#endif

namespace cox {
	// --- NetHelper 实现 ---
	uint16_t NetHelper::Ntohs(uint16_t v) { return ntohs(v); }
	uint16_t NetHelper::Htons(uint16_t v) { return htons(v); }
	uint32_t NetHelper::Ntohl(uint32_t v) { return ntohl(v); }
	uint32_t NetHelper::Htonl(uint32_t v) { return htonl(v); }
	string   NetHelper::GetHostName() {
        char hostname[256] = {0};
#ifdef WIN32
		if (gethostname(hostname, sizeof(hostname)) == 0) {
			return string(hostname);
		}
#else
		if (gethostname(hostname, sizeof(hostname)) == 0) {
			return string(hostname);
		}
#endif
		return ""; // 获取失败
	}
	// --- NetAddr 实现 ---
	NetAddr::NetAddr(const string &host, const unsigned &port) : host(host), port(port) {
		if (port > 65535) this->port = 0;
	}
	bool NetAddr::parseIPWithPort(const string &ipWithPort) {
		string::size_type colonPos = ipWithPort.rfind(':');
		if (colonPos != string::npos) {
			if (sscanf(ipWithPort.c_str() + colonPos + 1, "%u", &port) != 1) return false;
		} else {
			port = 80; // 默认端口
		}
		host = ipWithPort.substr(0, colonPos);
		return true;
	}
	bool NetAddr::toSockAddr(struct sockaddr_in *addr) const {
		if (!addr) return false;
		memset(addr, 0, sizeof(struct sockaddr_in)); // 清零结构体
		addr->sin_family = AF_INET;
		addr->sin_port   = htons(port);
		if (host.empty()) {
			addr->sin_addr.s_addr = htonl(INADDR_ANY); // 绑定到任意地址
			return true;
		}
		// 优先尝试使用getaddrinfo，它更现代且能同时处理IPv4和IPv6
		struct addrinfo hints = {}, *res;
		hints.ai_family       = AF_INET; // 强制IPv4
		hints.ai_socktype     = SOCK_STREAM;
		if (getaddrinfo(host.c_str(), nullptr, &hints, &res) == 0) {
			addr->sin_addr = ((struct sockaddr_in *) res->ai_addr)->sin_addr;
			freeaddrinfo(res);
			return true;
		}
		// getaddrinfo失败，回退到inet_addr (仅限IP地址)
		addr->sin_addr.s_addr = inet_addr(host.c_str());
		return addr->sin_addr.s_addr != INADDR_NONE;
	}
	// --- 全局运算符重载 ---
	bool operator<(const NetAddr &left, const NetAddr &right) {
		if (left.host != right.host) return left.host < right.host;
		return left.port < right.port;
	}

	// --- 辅助函数 ---
	namespace {
		int transVec2FdSet(vector<int> *fdVec, fd_set *fdSet) {
			int maxFd = -1;
			if (fdVec) {
				for (int fd: *fdVec) {
					if (fd > 0) {
						FD_SET(static_cast<unsigned>(fd), fdSet);
						if (fd > maxFd) maxFd = fd;
					}
				}
			}
			return maxFd;
		}
		void matchVecWithFdSet(vector<int> *fdVec, fd_set *fdSet) {
			if (!fdVec) return;
			auto it = fdVec->begin();
			while (it != fdVec->end()) {
				if (!FD_ISSET(*it, fdSet)) {
					it = fdVec->erase(it);
				} else {
					++it;
				}
			}
		}
		int transVec2FdSet(Socket::OpType type, vector<Socket *> *vec, fd_set *fdSet) {
			int maxFd = -1;
			if (vec) {
				for (Socket *sock: *vec) {
					if (sock && sock->isValid()) {
						int fd = sock->setFdSet(type, fdSet);
						if (fd > maxFd) maxFd = fd;
					}
				}
			}
			return maxFd;
		}
		void matchVecWithFdSet(Socket::OpType type, vector<Socket *> *vec, fd_set *fdSet) {
			if (!vec) return;
			vector<Socket *> readySockets;
			for (Socket *sock: *vec) {
				if (sock && sock->isValid() && sock->matchFdSet(type, fdSet)) {
					readySockets.push_back(sock);
				}
			}
			*vec = std::move(readySockets);
		}
		inline int maxInt(int a, int b) { return a > b ? a : b; }
		timeval    toTimeval(const TimeVal &tv) { return {static_cast<time_t>(tv.s), static_cast<suseconds_t>(tv.ms * 1000 + tv.us)}; }
	} // anonymous namespace

	// --- Socket 实现 ---
	Socket::Socket(const Type &_type) : type(_type), fd(-1) {
		if (!initSocket()) {
			// 初始化失败，fd将保持为-1
			cerr << "Socket creation failed, error: " << getError() << endl;
		}
	}
	Socket::~Socket() {
		if (fd > 0) {
			SOCKETCLOSE(fd);
			fd = -1;
		}
	}
	bool Socket::isValid() const { return fd != -1; }
	bool Socket::initSocket() {
		int protocol  = (type == TCP) ? IPPROTO_TCP : IPPROTO_UDP;
		int sock_type = (type == TCP) ? SOCK_STREAM : SOCK_DGRAM;
		fd            = socket(AF_INET, sock_type, protocol);
		return isValid();
	}
	bool Socket::addMemberShip(const string &groupIP, const string &localIP) {
		if (!isValid()) return false;
		struct ip_mreq mreq;
		mreq.imr_multiaddr.s_addr = inet_addr(groupIP.c_str());
		mreq.imr_interface.s_addr = inet_addr(localIP.c_str());
		// 设置本地回环，以便同一台主机上的多个进程可以接收组播数据
		char loop = 1;
		if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) < 0) {
			return false;
		}
		return setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, sizeof(mreq)) >= 0;
	}
	bool Socket::dropMemberShip(const string &groupIP, const string &localIP) {
		if (!isValid()) return false;
		struct ip_mreq mreq;
		mreq.imr_multiaddr.s_addr = inet_addr(groupIP.c_str());
		mreq.imr_interface.s_addr = inet_addr(localIP.c_str());
		return setsockopt(fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char *) &mreq, sizeof(mreq)) >= 0;
	}
	bool Socket::bind(const NetAddr &addr) {
		if (!isValid()) return false;
		struct sockaddr_in socketAddr;
		if (!addr.toSockAddr(&socketAddr)) return false;
		this->addr = addr;
		return ::bind(fd, (struct sockaddr *) &socketAddr, sizeof(socketAddr)) == 0;
	}
	bool Socket::listen(const int &num) {
		if (!isValid()) return false;
		return ::listen(fd, num) == 0;
	}
	bool Socket::connect(const NetAddr &addr, const TimeVal &tv) {
		if (!isValid()) return false;
		struct sockaddr_in socketAddr;
		if (addr.host.empty() || !addr.toSockAddr(&socketAddr)) return false;
		this->addr = addr;
		// 非阻塞连接逻辑
		if (tv > TimeVal()) {
			// 保存原始阻塞状态
			bool wasBlocking = true;
			// 设置非阻塞
			if (!setNotBlock(true)) {
				return false;
			}
			wasBlocking = false;

			int res = ::connect(fd, (struct sockaddr *) &socketAddr, sizeof(socketAddr));
			if (res == 0) {               // 立即成功
				setNotBlock(wasBlocking); // 恢复原始状态
				return true;
			}

			int err = SOCKETERR();
			if (err != SOCKET_IN_PROGRESS && err != SOCKET_WOULD_BLOCK) {
				setNotBlock(wasBlocking); // 恢复原始状态
				return false;
			}

			// 使用select等待连接完成
			bool canWrite = canSend(tv);
			// 恢复原始阻塞状态
			setNotBlock(wasBlocking);
			if (!canWrite) return false; // 超时或错误
			// 再次检查socket错误，确认连接是否真正成功
			return !isDisconnected();
		} else {
			// 阻塞连接
			return ::connect(fd, (struct sockaddr *) &socketAddr, sizeof(socketAddr)) == 0;
		}
	}
	bool Socket::reconnect(const NetAddr &addr, const TimeVal &tv) {
		// 1. 关闭旧连接
		if (isValid()) {
			SOCKETCLOSE(fd);
		}
		// 2. 创建新socket
		if (!initSocket()) {
			return false;
		}
		// 3. 进行新连接
		return connect(addr, tv);
	}
	bool Socket::isDisconnected() const {
		if (!isValid()) return true;
		int       error = 0;
		socklen_t len   = sizeof(error);
		if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char *) &error, &len) < 0) {
			return true; // getsockopt本身失败，视为断开
		}
		return error != 0; // error非0表示有错误，如连接被重置
	}
	unique_ptr<Socket> Socket::accept() {
		if (!isValid()) return nullptr;
		sockaddr_in clientAddr;
		socklen_t   addrLen  = sizeof(clientAddr);
		int         clientFd = ::accept(fd, (struct sockaddr *) &clientAddr, &addrLen);
		if (clientFd < 0) {
			return nullptr;
		}
		char ipStr[INET_ADDRSTRLEN] = {0};
#ifdef WIN32
		// InetNtop is available on Vista+
		inet_ntop(AF_INET, &clientAddr.sin_addr, ipStr, sizeof(ipStr));
#else
		inet_ntop(AF_INET, &clientAddr.sin_addr, ipStr, sizeof(ipStr));
#endif
		unsigned port = ntohs(clientAddr.sin_port);
		NetAddr  addr(ipStr, port);
		return unique_ptr<Socket>(new Socket(clientFd, addr));
	}
	bool Socket::canSend(const TimeVal &tv) {
		if (!isValid()) return false;
		fd_set writeSet;
		FD_ZERO(&writeSet);
		FD_SET(static_cast<unsigned>(fd), &writeSet);
		timeval ostv      = toTimeval(tv);
		int     selectRes = ::select(fd + 1, nullptr, &writeSet, nullptr, tv.s < 0 ? nullptr : &ostv);
		return selectRes > 0 && FD_ISSET(fd, &writeSet);
	}

	long long Socket::send(const char *buf, const size_t len, const int flags) {
		if (!isValid() || !buf || len == 0) return -1;
		long long sendLen = ::send(fd, buf, static_cast<int>(len), flags);
		return sendLen;
	}

	long long Socket::sendto(const char *buf, const size_t len, const NetAddr &addr, const int flags) {
		if (!isValid() || !buf) return -1;
		struct sockaddr_in socketAddr;
		if (!addr.toSockAddr(&socketAddr)) return -1;
		long long sendLen = ::sendto(fd, buf, static_cast<int>(len), flags, (struct sockaddr *) &socketAddr, sizeof(socketAddr));
		return sendLen;
	}
	bool Socket::canRecv(const TimeVal &tv) {
		if (!isValid()) return false;
		fd_set readSet;
		FD_ZERO(&readSet);
		FD_SET(static_cast<unsigned>(fd), &readSet);
		timeval ostv      = toTimeval(tv);
		int     selectRes = ::select(fd + 1, &readSet, nullptr, nullptr, tv.s < 0 ? nullptr : &ostv);
		return selectRes > 0 && FD_ISSET(fd, &readSet);
	}
	long long Socket::recv(char *buf, const size_t len, const int flags) {
		if (!isValid() || !buf) return -1;
		long long recvLen = ::recv(fd, buf, static_cast<int>(len), flags);
		return recvLen;
	}
	long long Socket::recvfrom(char *buf, const size_t len, NetAddr &addr, const int flags) {
		if (!isValid() || !buf) return -1;
		struct sockaddr_in fromAddr;
		socklen_t          addrLen = sizeof(fromAddr);
		long long          recvLen = ::recvfrom(fd, buf, static_cast<int>(len), flags, (struct sockaddr *) &fromAddr, &addrLen);
		if (recvLen < 0) {
			return -1;
		}
		char ipStr[INET_ADDRSTRLEN] = {0};
#ifdef WIN32
		inet_ntop(AF_INET, &fromAddr.sin_addr, ipStr, sizeof(ipStr));
#else
		inet_ntop(AF_INET, &fromAddr.sin_addr, ipStr, sizeof(ipStr));
#endif
		addr.host = ipStr;
		addr.port = ntohs(fromAddr.sin_port);
		return recvLen;
	}
	int     Socket::getFd() const { return fd; }
	int     Socket::getError() const { return SOCKETERR(); }
	NetAddr Socket::getAddr() const { return addr; }
	bool    Socket::setReuseAddr(bool on) {
        if (!isValid()) return false;
        int opt = on ? 1 : 0;
        return setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &opt, sizeof(opt)) >= 0;
	}
	bool Socket::setNotBlock(bool on) {
		if (!isValid()) return false;
#ifdef WIN32
		u_long mode = on ? 1 : 0;
		return ioctlsocket(fd, FIONBIO, &mode) == 0;
#else
		int flags = fcntl(fd, F_GETFL, 0);
		if (flags < 0) return false;
		return fcntl(fd, F_SETFL, on ? (flags | O_NONBLOCK) : (flags & ~O_NONBLOCK)) == 0;
#endif
	}
	bool Socket::setLinger(bool on, unsigned linger_seconds) {
		if (!isValid()) return false;
		struct linger so_linger;
		so_linger.l_onoff  = on ? 1 : 0;
		so_linger.l_linger = linger_seconds;
		return setsockopt(fd, SOL_SOCKET, SO_LINGER, (const char *) &so_linger, sizeof(so_linger)) == 0;
	}
	bool Socket::routeAdd(const char *dest, const char *gate, long mask) {
		// 明确标记为未实现，避免误导
		(void) dest;
		(void) gate;
		(void) mask; // 抑制未使用参数警告
		cerr << "Warning: Socket::routeAdd is not implemented." << endl;
		return false;
	}
	void Socket::reverseSeq(char *data, const size_t len) {
		if (!data || len <= 1) return;
		for (size_t i = 0; i < len / 2; ++i) {
			std::swap(data[i], data[len - i - 1]);
		}
	}
	int Socket::setFdSet(OpType type, void *fdset) {
		(void) type; // OpType对于fd_set是通用的
		if (!isValid()) return -1;
		FD_SET(static_cast<unsigned>(fd), (fd_set *) fdset);
		return fd;
	}
	bool Socket::matchFdSet(OpType type, void *fdset) {
		(void) type;
		if (!isValid()) return false;
		return FD_ISSET(fd, (fd_set *) fdset);
	}

	int Socket::select(vector<int> *readVec, vector<int> *writeVec, vector<int> *errVec, const TimeVal &tv) {
		if (!readVec && !writeVec && !errVec) return 0;
		fd_set rSet, wSet, eSet;
		FD_ZERO(&rSet);
		FD_ZERO(&wSet);
		FD_ZERO(&eSet);
		int maxFd         = transVec2FdSet(readVec, &rSet);
		maxFd             = maxInt(maxFd, transVec2FdSet(writeVec, &wSet));
		maxFd             = maxInt(maxFd, transVec2FdSet(errVec, &eSet));
		timeval ostv      = toTimeval(tv);
		int     selectRes = ::select(maxFd + 1, &rSet, &wSet, &eSet, tv.s < 0 ? nullptr : &ostv);
		if (selectRes > 0) {
			matchVecWithFdSet(readVec, &rSet);
			matchVecWithFdSet(writeVec, &wSet);
			matchVecWithFdSet(errVec, &eSet);
		} else { // 错误或超时，清空输出向量
			if (readVec) readVec->clear();
			if (writeVec) writeVec->clear();
			if (errVec) errVec->clear();
		}
		return selectRes;
	}
	int Socket::select(vector<Socket *> *readVec, vector<Socket *> *writeVec, vector<Socket *> *errVec, const TimeVal &tv) {
		if (!readVec && !writeVec && !errVec) return 0;
		fd_set rSet, wSet, eSet;
		FD_ZERO(&rSet);
		FD_ZERO(&wSet);
		FD_ZERO(&eSet);
		int maxFd          = transVec2FdSet(OP_READ, readVec, &rSet);
		maxFd              = maxInt(maxFd, transVec2FdSet(OP_WRITE, writeVec, &wSet));
		maxFd              = maxInt(maxFd, transVec2FdSet(OP_ERR, errVec, &eSet));
		timeval ostv       = toTimeval(tv);
		int     selectRes  = ::select(maxFd + 1, &rSet, &wSet, &eSet, tv.s < 0 ? nullptr : &ostv);
		int     readyCount = 0;
		if (selectRes > 0) {
			matchVecWithFdSet(OP_READ, readVec, &rSet);
			matchVecWithFdSet(OP_WRITE, writeVec, &wSet);
			matchVecWithFdSet(OP_ERR, errVec, &eSet);
			if (readVec) readyCount += readVec->size();
			if (writeVec) readyCount += writeVec->size();
			if (errVec) readyCount += errVec->size();
		} else { // 错误或超时，清空输出向量
			if (readVec) readVec->clear();
			if (writeVec) writeVec->clear();
			if (errVec) errVec->clear();
		}
		return selectRes > 0 ? readyCount : selectRes;
	}
	// --- 私有构造函数 ---
	Socket::Socket(const int &fd, const NetAddr &addr) : type(TCP), fd(fd), addr(addr) {}
	string Socket::getInfo() const { return "Socket(" + string(type == TCP ? "TCP" : "UDP") + ",fd=" + (isValid() ? to_string(fd) : "invalid") + ")"; }
} // namespace cox
